package com.dwy2002.common;

import com.dwy2002.enums.Status;
import lombok.Getter;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author 杜伟毅
 * @version 2.2
 * @since 2025/01/10
 */
@Getter
public class Result<T> {
    // 复用常用无数据实例
    private static final Result<?> NO_CONTENT = new Result<>(Status.NO_CONTENT, null);
    private static final Result<?> INTERNAL_ERROR = new Result<>(Status.INTERNAL_ERROR, null);
    /**
     * 状态码
     */
    private int code;
    /**
     * 提示文本
     */
    private String message;
    /**
     * 返回数据
     */
    private T data;
    /**
     * 多项错误数据
     */
    private List<String> errors;

    // 私有构造方法
    private Result() {
    }

    private Result(Status status, T data) {
        this(status.code, status.defaultMessage, data);
    }

    private Result(Status status, String message, T data) {
        this.code = status.code;
        this.message = StringUtils.hasText(message) ? message : status.defaultMessage;
        this.data = data;
    }

    private Result(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    /**
     * 核心构建方法
     *
     * @param status  状态码
     * @param message 信息
     * @param data    数据
     * @author 杜伟毅
     * @since 2025/2/19 0019 16:01
     */
    public static <T> Result<T> of(Status status, String message, T data) {
        return new Result<>(status, message, data);
    }


    // 快捷方法

    /**
     * 用途：请求成功。
     * 示例：GET 请求成功获取资源。
     *
     * @param data 要返回的数据
     * @author 杜伟毅
     * @since 2024/11/27 0027 12:49
     */
    public static <T> Result<T> success(T data) {
        return new Result<>(Status.OK, data);
    }

    /**
     * 用途：请求成功并且新资源被创建。
     * 示例：POST 请求成功创建资源。
     *
     * @param message 成功信息
     * @author 杜伟毅
     * @since 2024/11/27 0027 12:49
     */
    public static <T> Result<T> created(String message) {
        return of(Status.CREATED, message, null);
    }

    /**
     * 用途：请求成功，但没有返回内容。
     *
     * @param message 成功信息
     * @author 杜伟毅
     * @since 2024/11/27 0027 12:49
     */
    public static <T> Result<T> noContent(String message) {
        return of(Status.NO_CONTENT, message, null);
    }

    /**
     * 用途：客户端发送的请求包含语法错误或无效参数。
     * 示例：登录请求中手机号错误或手机号为空。
     *
     * @param status  状态码
     * @param message 失败信息
     * @author 杜伟毅
     * @since 2024/11/27 0027 12:49
     */
    public static <T> Result<T> fail(Status status, String message) {
        return of(status, message, null);
    }

    /**
     * 用途：服务器内部错误，无法完成请求。
     * 示例：服务器端代码抛出未处理的异常。
     *
     * @author 杜伟毅
     * @since 2024/11/27 0027 12:49
     */
    public static <T> Result<T> error() {
        @SuppressWarnings("unchecked")
        Result<T> result = (Result<T>) INTERNAL_ERROR;
        return result;
    }

    /**
     * 用途：服务器内部错误，无法完成请求,。
     * 示例：服务器端代码抛出未处理的异常。
     *
     * @param msg 错误信息
     * @return 返回带有精确错误码（UUID生成）的信息，方便后端人员查找问题
     * @author 杜伟毅
     * @since 2025/3/9 0009 21:24
     */
    public static <T> Result<T> error(String msg) {
        return of(Status.INTERNAL_ERROR, msg, null);
    }

    /**
     * 支持多错误消息
     *
     * @param status Status 状态码
     * @param error  错误提示
     * @return 错误消息集合
     * @author 杜伟毅
     * @since 2025/2/1 0001 15:17
     */
    public static <T> Result<T> fail(Status status, Object error) {
        Result<T> result = new Result<>();
        result.code = status.code;
        if (error instanceof Collection) {
            result.errors = new ArrayList<>((Collection<String>) error);
        } else {
            result.message = error.toString();
        }
        return result;
    }


    //-----------------------------高级方法-------------------------------------------------

    /**
     * 修改和删除方法
     *
     * @param result     表示操作是否成功的布尔值
     * @param successMsg 操作成功时返回的消息
     * @param failMsg    操作失败时返回的消息
     * @author 杜伟毅
     * @since 2025/2/25 0025 13:04
     */
    public static <T> Result<T> handleResult(boolean result, String successMsg, String failMsg) {
        return result ?
                noContent(successMsg) :
                fail(Status.BAD_REQUEST, failMsg);
    }

    /**
     * 修改和删除方法
     *
     * @param result      表示操作是否成功的布尔值
     * @param errorStatus 操作失败时返回的状态码或状态信息
     * @param successMsg  操作成功时返回的消息
     * @param failMsg     操作失败时返回的消息
     * @author 杜伟毅
     * @since 2025/2/25 0025 13:04
     */
    public static <T> Result<T> handleResult(boolean result, Status errorStatus, String successMsg, String failMsg) {
        return result ?
                noContent(successMsg) :
                fail(errorStatus, failMsg);
    }

    /**
     * 添加方法
     *
     * @param result      表示操作是否成功的布尔值
     * @param errorStatus 操作失败时返回的状态码或状态信息
     * @param successMsg  操作成功时返回的消息
     * @param failMsg     操作失败时返回的消息
     * @author 杜伟毅
     * @since 2025/2/25 0025 13:04
     */
    public static <T> Result<T> saveResult(boolean result, Status errorStatus, String successMsg, String failMsg) {
        return result ?
                created(successMsg) :
                fail(errorStatus, failMsg);
    }

    /**
     * 添加方法
     *
     * @param result     表示操作是否成功的布尔值
     * @param successMsg 操作成功时返回的消息
     * @param failMsg    操作失败时返回的消息
     * @author 杜伟毅
     * @since 2025/2/25 0025 13:04
     */
    public static <T> Result<T> saveResult(boolean result, String successMsg, String failMsg) {
        return result ?
                created(successMsg) :
                fail(Status.BAD_REQUEST, failMsg);
    }

/*
2.0：
代码复用：
核心逻辑收敛到 of() 方法，减少 60% 重复代码
防御性处理：1.自动填充默认消息 2.禁止直接 new 对象
灵活扩展：新增状态码只需修改 Status 枚举

2.1：
扩展支持多错误消息，可以这样返回消息：
{
  "code": 400,
  "errors": [
    "课程ID不能为空!",
    "价格不能为0或空!",
    "状态错误，没有这个状态选项!"
  ]
}

2.2
增加高级方法
优化条件判断冗余
封装业务结果校验流程
 */
}